using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Threading;
using Microsoft.Office.Project.EPMSync.Config.Library;
using System.Reflection;
using System.Drawing.Drawing2D;
using Microsoft.Office.Project.EPMSync.Service.Monitor.Properties;

namespace Microsoft.Office.Project.EPMSync.Service.Monitor
{
    public partial class EPMSyncChanges : UserControl
    {
        private ManualResetEvent _pause = new ManualResetEvent(false);
        Thread _workerThread;

        delegate void SetStatusCallback();

        private SqlConnection _connectionString;
        private const string _archiveQueryString = "SELECT COUNT(*) FROM esQUEUE_ATTRIBUTE_EVENTS_ARCHIVE";
        private const string _activeQueryString = "SELECT COUNT(*) FROM esQUEUE_ATTRIBUTE_EVENTS";

        private string _textBoxActiveChanges;
        private string _textBoxArchiveChanges;

        private NetStatusReceiver _netStatusReceiver = null;

        LinearGradientBrush _redBrush;
        LinearGradientBrush _greenBrush;
        LinearGradientBrush _yellowBrush;
        LinearGradientBrush _greyBrush;

        Color _trimColor = Color.Red;
        private int _coloredBorderWidth = 6;

        public EPMSyncChanges()
        {
            InitializeComponent();
            _netStatusReceiver = new NetStatusReceiver();
            _netStatusReceiver.RaiseNetStatusEvent += new EventHandler<NetStatusEventArgs>(netStatusReceiver_RaiseNetStatusEvent);

            _redBrush = new LinearGradientBrush(
                new Rectangle(0, 0, this.Size.Width, this.Size.Height),
                Color.Red,
                Color.MistyRose,
                LinearGradientMode.Vertical);

            _greenBrush = new LinearGradientBrush(
                new Rectangle(0, 0, this.Size.Width, this.Size.Height),
                Color.Green,
                Color.LightGreen,
                LinearGradientMode.Vertical);

            _yellowBrush = new LinearGradientBrush(
                new Rectangle(0, 0, this.Size.Width, this.Size.Height),
                Color.Yellow,
                Color.LightYellow,
                LinearGradientMode.Vertical);

            _greyBrush = new LinearGradientBrush(
                new Rectangle(0, 0, this.Size.Width, this.Size.Height),
                Color.Gray,
                Color.LightGray,
                LinearGradientMode.Vertical);

        }

        public void netStatusReceiver_RaiseNetStatusEvent(object sender, NetStatusEventArgs e)
        {
            if (e != null)
            {
                this.textBoxStatus.Text = e.Message;
            }
        }



        public void StartControl()
        {

            try
            {
                _trimColor = Color.Yellow;

                // Read the database connection string
                Assembly epmAssembly = Assembly.GetExecutingAssembly();
                string fullPath = epmAssembly.Location;
                string directory = fullPath.Substring(0, fullPath.LastIndexOf(@"\") + 1);

                SyncConfigFile configFile = new SyncConfigFile(directory + "EPMSync.config");
                SyncConfig config = configFile.SyncConfiguration;

                string PPSDBConnString = config.PortfolioServerDatabaseConnectionString;

                // Connect to the database
                if (string.IsNullOrEmpty(PPSDBConnString))
                    throw new ArgumentNullException("PortfolioServerDatabaseConnectionString", Resources.NoLoadConfig);
                _connectionString = new SqlConnection(PPSDBConnString);
                _connectionString.Open();
            }
            catch(Exception ex)
            {
                labelActive.Text = Resources.NoDBConnection;
                labelArchive.Text = ex.Message;
                textBoxActiveChanges.Hide();
                textBoxArchiveChanges.Hide();
                _trimColor = Color.Red; 
                //this.BackColor = Color.Red;

                return;
            }

            // Read the service state
            UpdateState();

            // Spawn thread to get updates on the control
            _workerThread = new Thread(new ThreadStart(UpdateMethod));
            _workerThread.Start();
            _pause.Set();

            _trimColor = Color.LightGreen;
        }

        public void StopControl()
        {
            _pause.Reset();
            Thread.Sleep(200);
            if (_workerThread != null)
                _workerThread.Abort();
            _pause.Set();
            _connectionString.Close();
            _netStatusReceiver.Stop();
        }

        //private SqlDataReader GetReader(string sqlQueryString)
        //{
        //    try
        //    {
        //        SqlCommand command = new SqlCommand(sqlQueryString, _connectionString);
        //        return command.ExecuteReader();
        //    }
        //    catch
        //    {
        //        return null;
        //    }
        //}

        private string GetChanges(string sqlQueryString)
        {
            try
            {
                SqlCommand command = new SqlCommand(sqlQueryString, _connectionString);
                return command.ExecuteScalar().ToString();
            }
            catch
            {
                return "0";
            }
        }

        public void UpdateState()
        {
            _textBoxActiveChanges = GetChanges(_activeQueryString);
            _textBoxArchiveChanges = GetChanges(_archiveQueryString);

            SetStatus();
        }

        private void SetStatus()
        {
            if (this.textBoxActiveChanges.InvokeRequired)
            {
                SetStatusCallback d = new SetStatusCallback(SetStatus);
                this.Invoke(d, new object[] { });
            }
            else
            {
                this.textBoxActiveChanges.Text = _textBoxActiveChanges;
                this.textBoxArchiveChanges.Text = _textBoxArchiveChanges;
            }
        }

        private void UpdateMethod()
        {
            int wakeupInterval = 1000;
            DateTime wakeupTime = DateTime.Now.AddMilliseconds(wakeupInterval);

            try
            {
                do
                {
                    if (DateTime.Now > wakeupTime)
                    {
                        UpdateState();
                        wakeupTime = DateTime.Now.AddMilliseconds(wakeupInterval);
                    }

                    // Wait before cycling.
                    Thread.Sleep(100);
                    // Block if the service is paused or is shutting down.
                    _pause.WaitOne();
                } while (true);
            }
            catch (ThreadAbortException)
            {
                Thread.ResetAbort();
            }
        }

        private void EPMSyncChanges_Paint(object sender, PaintEventArgs e)
        {
            Pen trimPen = null;

            if (_trimColor == Color.Red)
                trimPen = new Pen(_redBrush);
            else if (_trimColor == Color.LightGreen)
                trimPen = new Pen(_greenBrush);
            else if (_trimColor == Color.Yellow)
                trimPen = new Pen(_yellowBrush);
            else
                trimPen = new Pen(_greyBrush);

            trimPen.Width = Convert.ToSingle(_coloredBorderWidth);
            int offset = 2 + (_coloredBorderWidth / 2);

            trimPen.LineJoin = System.Drawing.Drawing2D.LineJoin.Round;

            Rectangle rectangle1 = new Rectangle(offset, offset, this.Size.Width - (offset * 2), this.Size.Height - (offset * 2));
            e.Graphics.DrawRectangle(trimPen, rectangle1);
            e.Graphics.DrawRectangle(Pens.Black, 2, 2, this.Size.Width - 4, this.Size.Height - 4);
            e.Graphics.DrawRectangle(Pens.Black, 2 + _coloredBorderWidth, 2 + _coloredBorderWidth, this.Size.Width - 4 - (2 * _coloredBorderWidth), this.Size.Height - 4 - (2 * _coloredBorderWidth));

            //Dispose of the pen.
            trimPen.Dispose();
        }


        private void EPMSyncChanges_DoubleClick(object sender, EventArgs e)
        {
            FormQueueDetails qd = new FormQueueDetails(_connectionString);
            qd.Show();
        }


    }
}
